#ifndef _RANDOM32_H
#define _RANDOM32_H

#include <climits>

#ifdef GALLIUMENGINE_DLL 
#define GALLIUMENGINE_API __declspec( dllexport )
#else
#define GALLIUMENGINE_API __declspec( dllimport )
#endif

namespace GalliumEngine
{

	/// Mersenne Twister random number generator.
	class GALLIUMENGINE_API Random32 
	{
	public:
	  Random32() 
	  { 
		  if (!initialize) seed(5489UL);
		  {
			initialize = true;
		  }
	  }

	  Random32(unsigned long s) 
	  { 
		  seed(s);
		  initialize = true; 
	  }

	  Random32(const unsigned long* arr, int size)
	  { 
		  seed(arr, size);
		  initialize = true; 
	  }

	  void seed(unsigned long seed);
	  void seed(const unsigned long* arr, int size);

	  unsigned long operator()() 
	  { 
		  return rand_int32(); 
	  }

	  virtual ~Random32() {}
	  unsigned long rand_int32();
	private:
	  static const int n = 624;
	  static const int m = 397;
	  static unsigned long state[n]; 
	  static int p; 
	  static bool initialize; 

	  //Random32(const Random32&);
	  void gen_state();
	  unsigned long twiddle(unsigned long, unsigned long);
	  //void operator=(const Random32&);
	};


	inline unsigned long Random32::twiddle(unsigned long u, unsigned long v) 
	{
	  return (((u & 0x80000000UL) | (v & 0x7FFFFFFFUL)) >> 1) ^ ((v & 1UL) ? 0x9908B0DFUL : 0x0UL);
	}

	inline unsigned long Random32::rand_int32() 
	{
	  if (p == n)
	  {
		  gen_state();
	  }

	  unsigned long x = state[p++];
	  x ^= (x >> 11);
	  x ^= (x << 7) & 0x9D2C5680UL;
	  x ^= (x << 15) & 0xEFC60000UL;
	  return x ^ (x >> 18);
	}
}

#endif